﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using Telerik.Web.UI;
using Medianamik.Core;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using Medianamik.Core.Sugar;
using Medianamik.Globalization;

namespace Medianamik.UI.Controls
{
    public class ComboTree : BaseMedianamikControl, IMedianamikControl, INamingContainer
    {

        RadComboBox _combo = new RadComboBox() { ID = ControlToValidateId };
        RadTreeView _tree = new RadTreeView();
        const int DEFAULT_WIDTH = 300;
        const int DEFAULT_HEIGHT = 300;

        protected virtual bool EnableResetButton
        {
            get
            {
                return true;
            }
        }

        void TreeNodeExpand(object sender, RadTreeNodeEventArgs e)
        {
            NodeExpand(e.Node);
        }

        void TreeNodeDataBound(object sender, RadTreeNodeEventArgs e)
        {
            if (!OptionNodeIds.Contains(new Guid(e.Node.Value)))
            {
                e.Node.Category = "Disabled";
                e.Node.CssClass += " rtDisabled";
                e.Node.HoveredCssClass = "rtDisabled";
                e.Node.SelectedCssClass = "rtDisabled";
            }
        }



        public override Type TypeOfValue
        {
            get { return typeof(Guid?); }
        }

        private List<Node> _rootNodes;
        protected virtual List<Node> RootNodes
        {
            get
            {
                if (_rootNodes == null)
                {
                    _rootNodes = NodeManager.GetChildNodes(ControlInfo.TreeRootNodeID.
                        GetValueOrDefault(MedianamikModules.ContentManagement));
                    _rootNodes.Sort((n1, n2) => n1.LongPosition.CompareTo(n2.LongPosition));
                    _rootNodes.RemoveAll(n => n.NodeTypeID.Equals(MedianamikTypes.MedianamikSyndication));
                    _rootNodes.RemoveAll(FilterNode);
                }
                return _rootNodes;
            }
        }

        protected virtual Guid[] OptionNodeIds
        {
            get
            {
                return ViewState["OptionNodeIds"] as Guid[]
                    ?? (Guid[])(ViewState["OptionNodeIds"] = Options.Select(o => o.NodeId).ToArray());
            }
        }

        protected RadTreeView Tree
        {
            get { return _tree; }
        }

        protected RadComboBox Combo
        {
            get { return _combo; }
        }



        protected virtual void NodeExpand(RadTreeNode parentNode)
        {
            List<Node> childs = NodeManager.GetChildNodes(new Guid(parentNode.Value));
            childs.Sort((n1, n2) => n1.LongPosition.CompareTo(n2.LongPosition));
            childs.RemoveAll(n => n.NodeTypeID.Equals(MedianamikTypes.MedianamikSyndication));
            childs.RemoveAll(n => FilterNode(n));

            foreach (Node child in childs)
            {
                var nd = new RadTreeNode(child.DisplayName, child.ID.ToString());

                if (child.HasChildren)
                    nd.ExpandMode = TreeNodeExpandMode.ServerSideCallBack;
                
                if (!OptionNodeIds.Contains(child.ID) || (IsSyndication && !ParentNode.LegitimateChildTypes.Any(t => t.ID.Equals(child.NodeTypeID))))
                {
                    nd.Category = "Disabled";
                    nd.CssClass += " rtDisabled";
                    nd.HoveredCssClass = "rtDisabled";
                    nd.SelectedCssClass = "rtDisabled";
                }

                parentNode.Nodes.Add(nd);
            }

            parentNode.ExpandMode = TreeNodeExpandMode.ClientSide;
            parentNode.Expanded = true;
        }

        protected virtual bool FilterNode(Node node)
        {
            return false;
        }

        protected override void CreateControlHierarchy(bool useDataSource)
        {
            Controls.Add(new LiteralControl("<table cellspacing=\"0\" cellpadding=\"0\"><tr><td>"));
            Controls.Add(_combo);
            _combo.ItemTemplate = new ComboTreeTemplate(_tree);
            _combo.Skin = "Medianamik";
            _combo.EnableEmbeddedSkins = false;

            _tree.NodeExpand += TreeNodeExpand;

            _tree.OnClientNodeClicking = "nodeClicking";
            _tree.Skin = "Medianamik";
            _tree.LoadingMessage = Translator.Translate("medianamik_controls", "treeview_loading_message");
            _tree.EnableEmbeddedSkins = false;

            if (useDataSource)
            {
                _combo.CausesValidation = false;
                _combo.Width = ControlInfo.Width.HasValue ? ControlInfo.Width.Value : DEFAULT_WIDTH;
                _combo.Height = ControlInfo.Height.HasValue ? ControlInfo.Height.Value : DEFAULT_HEIGHT;
                _combo.Items.Add(new RadComboBoxItem());

                foreach (var option in RootNodes)
                {
                    var nd = new RadTreeNode(option.DisplayName, option.ID.ToString());
                    
                    if (option.HasChildren)
                        nd.ExpandMode = TreeNodeExpandMode.ServerSideCallBack;

                    if (!OptionNodeIds.Contains(option.ID) || (IsSyndication && ParentNode.LegitimateChildTypes.Any(t => t.ID.Equals(option.NodeTypeID))))
                    {
                        nd.Category = "Disabled";
                        nd.CssClass += " rtDisabled";
                        nd.HoveredCssClass = "rtDisabled";
                        nd.SelectedCssClass = "rtDisabled";
                    }

                    _tree.Nodes.Add(nd);
                }

                var node = default(Node);
                if (DataSource != null
                    && (node = NodeManager.GetNode((Guid)DataSource)) != null)
                {
                    RadTreeNode treeNode = _tree.FindNodeByValue(node.ID.ToString());

                    if (treeNode == null)
                    {
                        List<Guid> parentIds = DataUtil.GetBottomToTopNodeIds(node.Path, true, 0);
                        parentIds.Reverse();

                        foreach (Guid id in parentIds)
                        {
                            treeNode = _tree.FindNodeByValue(id.ToString());
                            if (treeNode != null)
                                NodeExpand(treeNode);
                        }

                        treeNode = _tree.FindNodeByValue(node.ID.ToString());
                    }

                    if (treeNode != null)
                    {
                        treeNode.Selected = true;
                        _combo.Items[0].Text = _tree.SelectedNode.Text;
                    }
                }
            }

            if (EnableResetButton)
                AddUnselectButton();
            Controls.Add(new LiteralControl("</td></tr></table>"));
        }

        private void AddUnselectButton()
        {
            var btnUnselect = new Button();

            Controls.Add(new LiteralControl("</td><td>&nbsp;</td><td>"));
            Controls.Add(btnUnselect);

            btnUnselect.Text = Translator.Translate("Medianamik_Controls", "UnselectTreeView");
            btnUnselect.Click += btnUnselect_Click;
            btnUnselect.CssClass = "Btn";

        }

        void btnUnselect_Click(object sender, EventArgs e)
        {
            _tree.ClearSelectedNodes();
            _tree.ClearCheckedNodes();
            _combo.Items[0].Text = "";
        }

        public override object GetValue()
        {
            EnsureChildControls();

            Guid? value = null;

            if (!String.IsNullOrEmpty(_tree.SelectedValue))
                value = new Guid(_tree.SelectedValue);

            return value;
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            string specializedScriptName = "OnClientNodeClickingHandlerFor" + PropertyName;

            Tree.OnClientNodeClicking = specializedScriptName;

            //Le script doit exister (différent) pour chaque instance de ComboTree
            string specializedScript = String.Concat("function " + specializedScriptName + "(sender, args) {\n",
                    " var comboBox = $find('" + Combo.ClientID + "');\n",
                    " var node = args.get_node();\n",
                    " var comboBoxItem = comboBox.get_items().getItem(0);\n",
                    "if (node.get_category() == \"Disabled\" || node.get_value() == comboBoxItem.get_value()) {\n",
                        "args.set_cancel(true);}\n",
                    "else {\n",
                        " comboBox.trackChanges();\n",
                        " comboBoxItem.set_value(node.get_value());\n",
                        " comboBox.set_text(node.get_text());\n",
                        " comboBox.commitChanges();\n",
                        " comboBox.hideDropDown();}\n",
                "}\n");

            string genericScript = String.Concat("function StopPropagation(e) {\n",
                    "if(typeof(e) == 'undefined' || !e) {\n",
                        " e = window.event;}\n",
                    "e.cancelBubble = true;\n",
                "}\n");

            ScriptManager.RegisterClientScriptBlock(Page, typeof(Page), specializedScriptName, specializedScript, true);
            ScriptManager.RegisterClientScriptBlock(Page, typeof(Page), "StopPropagation", genericScript, true);
        }

    }

    public class ComboTreeTemplate : ITemplate
    {

        RadTreeView _tree;



        public ComboTreeTemplate(RadTreeView tree)
        {
            _tree = tree;
        }









        public void InstantiateIn(Control container)
        {
            HtmlGenericControl div = new HtmlGenericControl("div");
            div.Attributes.Add("onclick", "StopPropagation(event)");
            container.Controls.Add(div);
            div.Controls.Add(_tree);
        }

    }
}
